package drds.server.datasource;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import drds.server.Server;
import drds.server.net.SessionContextGroupShareResources;

/**
 * Schema --> ConnectionQueue
 * 
 * @author 曹正辉<330937205@qq.com>
 */
public class SchemaToConnectionQueueMap {

	private final ConcurrentHashMap<String, ConnectionHolderQueue> schemaToConnectionQueueMap = new ConcurrentHashMap<String, ConnectionHolderQueue>();

	/**
	 * 根据schema获取ConnectionHolderQueue
	 */
	public ConnectionHolderQueue getConnectionHolderQueue(String schema) {
		ConnectionHolderQueue connectionHolderQueue = schemaToConnectionQueueMap.get(schema);
		if (connectionHolderQueue == null) {
			ConnectionHolderQueue newConnectionHolderQueue = new ConnectionHolderQueue();
			connectionHolderQueue = schemaToConnectionQueueMap.putIfAbsent(schema, newConnectionHolderQueue);
			return (connectionHolderQueue == null) ? newConnectionHolderQueue : connectionHolderQueue;
		}
		return connectionHolderQueue;
	}

	/**
	 * 从RDS实例获取数据库连接,如果不是当前的schema,则获取其他的schema然后设置schema。
	 */
	public IConnectionHolder getConnectionHolder(final String schema) {
		final ConnectionHolderQueue connectionHolderQueue = schemaToConnectionQueueMap.get(schema);
		IConnectionHolder connectionHolder = getConnectionHolderFrom(connectionHolderQueue);
		/**
		 * 如果当前的schema不能获取数据库连接,则从同一个数据库实例的其他schema获取数据库连接。
		 */
		if (connectionHolder != null) {
			return connectionHolder;
		} else {

			for (ConnectionHolderQueue $connectionHolderQueue : schemaToConnectionQueueMap.values()) {
				if (connectionHolderQueue != $connectionHolderQueue) {
					connectionHolder = getConnectionHolderFrom($connectionHolderQueue);
					if (connectionHolder != null) {
						return connectionHolder;
					}
				}
			}
		}
		return null;
	}

	/**
	 * 从ConnectionHolderQueue获取数据库连接
	 * 
	 */
	private IConnectionHolder getConnectionHolderFrom(ConnectionHolderQueue connectionHolderQueue) {

		IConnectionHolder connectionHolder = null;
		if (connectionHolderQueue != null && ((connectionHolder = connectionHolderQueue.getConnectionHolder()) != null)) {
			return connectionHolder;
		} else {
			return null;
		}

	}

	public Collection<ConnectionHolderQueue> values() {
		return schemaToConnectionQueueMap.values();
	}

	public int getActiveCountOfSchema(String schema, DataSource dataSource) {
		int total = 0;
		for (SessionContextGroupShareResources processor : Server.getInstance().getSessionContextGroupShareResources()) {
			for (IConnectionHolder connectionHolder : processor.getConnectionHolderMap().values()) {
				ConnectionHolder $connectionHolder = (ConnectionHolder) connectionHolder;
				if ($connectionHolder.getSchema().equals(schema) && //
						$connectionHolder.getDataSource() == dataSource && //
						$connectionHolder.isBorrowed()) {//
					total++;
				}
			}
		}
		return total;
	}

	public int getActiveCountOfDataSource(DataSource dataSource) {
		int total = 0;
		for (SessionContextGroupShareResources processor : Server.getInstance().getSessionContextGroupShareResources()) {
			for (IConnectionHolder connectionHolder : processor.getConnectionHolderMap().values()) {
				ConnectionHolder $connectionHolder = (ConnectionHolder) connectionHolder;
				if ($connectionHolder.getDataSource() == dataSource && //
						$connectionHolder.isBorrowed() && //
						!$connectionHolder.isClosed()) {//
					total++;
				}
			}
		}
		return total;
	}

	public void clearConnectionHolderList(String reason, DataSource dataSource) {
		for (SessionContextGroupShareResources processor : Server.getInstance().getSessionContextGroupShareResources()) {
			ConcurrentMap<Long, IConnectionHolder> connectionHolderMap = processor.getConnectionHolderMap();
			Iterator<Entry<Long, IConnectionHolder>> iterator = connectionHolderMap.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Long, IConnectionHolder> entry = iterator.next();
				IConnectionHolder connectionHolder = entry.getValue();
				connectionHolder.close(reason);
				iterator.remove();
			}

		}
		schemaToConnectionQueueMap.clear();
	}

	/**
	 * 从 NIOProcessor 将 BackendConnection 移除到 old connection 待回收区
	 */
	public List<IConnectionHolder> shiftConnectionHolderList(DataSource dataSource) {

		List<IConnectionHolder> connectionHolderList = new ArrayList<IConnectionHolder>();

		for (SessionContextGroupShareResources processor : Server.getInstance().getSessionContextGroupShareResources()) {
			ConcurrentMap<Long, IConnectionHolder> connectionHolderMap = processor.getConnectionHolderMap();
			Iterator<Entry<Long, IConnectionHolder>> iterator = connectionHolderMap.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Long, IConnectionHolder> entry = iterator.next();
				IConnectionHolder connectionHolder = entry.getValue();
				if (((ConnectionHolder) connectionHolder).getDataSource() == dataSource) {
					connectionHolderList.add(connectionHolder);
					iterator.remove();
				}
			}
		}
		schemaToConnectionQueueMap.clear();

		return connectionHolderList;
	}

}
